package com.stone.inventory.sharding.infra.hash;

import java.security.MessageDigest;

/**
 * Ketama hash 算法
 *
 * @author Mr_wenpan@163.com 2021/8/16 11:53 下午
 */
public class Ketama {

    /**
     * key 生成 hash值
     *
     * @param key key
     * @return hash值
     */
    public static long hash(String key) {

        byte[] keyBytes = computeMd5(key);
        // 拼凑成一个64为的long型值
        long rv = ((long) (keyBytes[3] & 0xFF) << 24)
                | ((long) (keyBytes[2] & 0xFF) << 16)
                | ((long) (keyBytes[1] & 0xFF) << 8)
                | (keyBytes[0] & 0xFF);
        return rv & 0xffffffffL;
    }

    /**
     * key生成md5
     *
     * @param key 入参
     * @return md5字节数组
     */
    private static byte[] computeMd5(String key) {

        MessageDigest md5;
        try {
            md5 = (MessageDigest) MESSAGE_DIGEST.clone();
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException("clone of MD5 not supported", e);
        }
        md5.update(key.getBytes());
        return md5.digest();
    }

    private final static String MD5 = "MD5";

    private static final MessageDigest MESSAGE_DIGEST;

    // 初始化 messageDigest
    static {
        try {
            MESSAGE_DIGEST = MessageDigest.getInstance(MD5);
        } catch (Exception ex) {
            throw new RuntimeException(MD5 + "not supported", ex);
        }
    }
}